/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SDRV_I2C_DRV_H_
#define SDRV_I2C_DRV_H_

#include "I2c_Types.h"
#include "Mcal_Delay.h"

#define SDRV_I2C_TIMEOUT 3000U
#define SDRV_I2C_MSG_IDLE 0
#define SDRV_I2C_MSG_RW 1

#define min(a, b)                       (a) < (b) ? (a) : (b)
#define I2C_DIV_ROUND_UP(n,d)           (uint32)(((n) / (float32)(d)) + 0.5)

#define CAL_BASE(value, clk_khz)        I2C_DIV_ROUND_UP(value * clk_khz, 1000000)
#define CAL_SCLL(value, clk_khz)        (CAL_BASE((value), (clk_khz)) - 1)
#define CAL_TA(value, clk_khz)          (CAL_BASE((value), (clk_khz)) - 1)
#define CAL_DVDAT(value, clk_khz)       ((CAL_BASE((value), (clk_khz)) / 2U) - 1U)
#define CAL_UNIT(value)                 (value)
#define CAL_MEXT(value, clk_khz)        (CAL_BASE((value), (clk_khz)))
#define CAL_SEXT(value, clk_khz)        (CAL_BASE((value), (clk_khz)))
#define CAL_STUCK(value, clk_khz)       ((uint64)(value) * (clk_khz) / 65536U)
#define CAL_SDARXHLD(value, clk_khz)    (CAL_BASE((value), (clk_khz)))
#define CAL_DATSPL(value)               (value)
#define CAL_BUF(value, clk_khz)         ((uint32)sdrv_I2c_Log2Uint(CAL_BASE((value), (clk_khz)) / 4U))
#define CAL_IDLE(value, clk_khz)        (CAL_BASE((value), (clk_khz)))

typedef struct sdrv_I2c_timing_cfg
{
    uint32 timscll;
    uint32 timtasclh;
    uint32 timtascll;
    uint32 timtasdal;
    uint32 timdvdat;
    uint32 timscll_h;
    uint32 timtasclh_h;
    uint32 timtascll_h;
    uint32 timtasdal_h;
    uint32 timdvdat_h;
    uint32 timunit;
    uint32 timmext;
    uint32 timsext;
    uint32 timstuck;
    uint32 timsdarxhld;
    uint32 timdatspl;
    uint32 timbuf;
    uint32 timidle;
} sdrv_I2c_timing_cfg_t;

typedef struct sdrv_I2c_timing
{
    uint32 divs;
    uint32 pcr2;
    uint32 pcr3;
    uint32 pcr4;
    uint32 pcr5;
} sdrv_I2c_timing_t;


typedef struct sdrv_I2c_dev
{
    I2c_adap_dev_t  adap;
    sdrv_I2c_mdev_t mdev;
} sdrv_I2c_dev_t;

int sdrv_I2c_master_irq_handler(uint32 irq, I2c_adap_dev_t *arg);
I2c_adap_dev_t *sdrv_I2c_adap_probe(sdrv_I2c_dev_t *dev, uint8 ChannelId, const I2c_adap_cfg_t *cfg, I2c_chan_id hwChannel );

I2c_init_state_t sdrv_I2c_init(I2c_adap_dev_t *adap);
Std_ReturnType sdrv_I2c_xfer(I2c_adap_dev_t *adap, I2c_msg_t *msgs, uint8 num);
int sdrv_I2c_recover(I2c_adap_dev_t *adap);
Std_ReturnType sdrv_I2c_deinit(I2c_adap_dev_t *adap);
void I2c_MainFunctionHandling(uint8 I2cId);
uint32 I2c_GetCoreId(void);
#endif
